package tcp_server

import (
	"context"
	"fmt"
	"net"
	"runtime"
)

/*
TCP 服务器连接处理的核心实现，主要处理 TCP 连接的接受和服务逻辑
*/

// TCP KeepAlive 监听器
type tcpKeepAliveListener struct {
	*net.TCPListener
}

// todo 思考点：继承方法覆写方法时，要使用非指针接口
// 使用值接收者而非指针接收者（指针接收者会导致方法递归）
func (ln tcpKeepAliveListener) Accept() (net.Conn, error) {
	tc, err := ln.AcceptTCP() // 接受 TCP 连接
	if err != nil {
		return nil, err
	}
	return tc, nil
}

// 上下文键定义
type contextKey struct {
	name string
}

func (k *contextKey) String() string {
	return "tcp_proxy context value " + k.name
}

type conn struct {
	server     *TcpServer         // 所属服务器
	cancelCtx  context.CancelFunc // 上下文取消函数
	rwc        net.Conn           // 原始网络连接
	remoteAddr string             // 客户端地址
}

// 连接关闭
func (c *conn) close() {
	c.rwc.Close() // 关闭底层网络连接
}

// 连接服务主逻辑
func (c *conn) serve(ctx context.Context) {
	// 异常恢复
	defer func() {
		if err := recover(); err != nil && err != ErrAbortHandler {
			const size = 64 << 10
			buf := make([]byte, size)
			buf = buf[:runtime.Stack(buf, false)]
			fmt.Printf("tcp: panic serving %v: %v\n%s", c.remoteAddr, err, buf)
		}
		c.close()
	}()

	// 设置连接信息
	c.remoteAddr = c.rwc.RemoteAddr().String()
	ctx = context.WithValue(ctx, LocalAddrContextKey, c.rwc.LocalAddr())
	// 验证处理器
	if c.server.Handler == nil {
		panic("handler empty")
	}

	// 调用业务处理器
	c.server.Handler.ServeTCP(ctx, c.rwc)
}
